Spring boot 笔记

JPA

  • 中文乱码

    1. 检查数据库编码
      • show variables like 'character_set_database';–查看该数据库使用的编码
      • alter database <数据库名> CHARACTER SET utf8;–修改编码为utf8
      • show create table <表名>;–查询表的编码,默认为:latin1
      • alter table <表名> character set utf8;–修改表的编码
    2. 检查JPA连接配置
      • spring.datasource.url后面加上characterEncoding=utf-8参数

    ps:后面才知道mysql的utf8是假的,只支持三字节的编码,utf8mb4才是现在称的真正utf8

View Object

因为前端要的字段可能跟数据库里的不同,或者要其他的数据,都在一个接口处返回,或者嵌套对象返回。
解决方法是使用一大片 getter setter for 语句来处理,代码极其不好看。于是花半天时间查阅 jpa 文档,发现可以用到 VO 来解决这些问题。
这里直接就贴上代码看一下就ok了。

1
2
3
4
5
6
7
8
9
10
11
public interface CompreGradeItem {
Integer getCompreRank();
// more...与数据库字段相同的直接写 get 方法
// 使用Value注解,获取到对象内的成员
@Value("#{target.student.major}")
String getMajor();
// 新建的键值对,可以利用 spel 实现简单的处理
// 要实现高级自定义,则编写自己的 bean 可以实现任意逻辑(下面一个)
@Value("#{@compreGradeBean.getAddGroup(target)}")
List<Object> getAddGroup();
}
1
2
3
4
5
6
7
8
9
10
11
12
@Component
public class CompreGradeBean {
private final CompreAddGradeRepository compreAddGradeRepository;
private final AwardBean awardBean;
@Autowired
public CompreGradeBean(CompreAddGradeRepository compreAddGradeRepository, AwardBean awardBean) {
this.compreAddGradeRepository = compreAddGradeRepository;
this.awardBean = awardBean;
}
public List<Object> getAddGroup(CompreGradeEntity compreGradeEntity) {
// 在这里编写自定义的方法,可以再进行查询。
}
1
2
3
public interface CompreGradeRepository extends JpaRepository<CompreGradeEntity, String> {
Page<CompreGradeItem> findAllByStudentMajorLikeAndStudentStuClassLikeAndYearTerm(String major,String stuClass,String yearTerm,Pageable pageable);
}

更新:
用这种方法,由于 jpa 无法预知程序员想要留下的字段,所以直接全部字段都查询出来,数据量少应该无所谓,但是最好还是写 nativeQuery 这样数据库压力会小点,但是返回的是 List<Object[]> 映射字段名就麻烦了。用 setter ?不存在的。尽量避免写出无意义,而且容易出错的代码
下面说一下我正在使用的方法:
配合 java 8 的特性 stream 实现字段映射:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 要映射的类
class ClassForm {
private String A;
private String B;
// 这里是一个需要调用 bean 的一个参数
private String C;
// getter setter
public static ClassForm map(Object[] i){
ClassForm tmp = new ClassForm();
tmp.setA(i[0]);
tmp.setB(i[1]);
return tmp;
}
// 模仿流式 api
public ClassForm setC(String c){
this.C = c;
return this;
}
}
1
2
3
4
// 在外层调用的时候
List<Object[]> x = repository.findAllByXXX(xxx);
List<ClassForm> r = x.stream().map(s->ClassForm.map(s).setC(myBean.getC(s[2]))).Collect(Collector.toList());
// 随后 r 就可以通过反射 API,自动生成 JSON 数据了
Author: whllhw
Link: https://whllhw.ml/posts/2018/03/21/Spring boot 笔记/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.